from Bases import BaseObject
from ..gtkBaseUI import BaseContainer
from ..devicetree import DeviceTree
from ..bases import widgets
from .. import editors
from ..bases import clutter_bases
#from DeviceSystem.Groups.AttributeGroup import ProxyGroup
from DeviceSystem.Groups.DeviceGroup import DeviceGroup
from modifiers.snapshot import Stack

class DeviceView(BaseContainer):
    topwidget_name = 'Device Definitions'
    topwidget_cls = widgets.HPane
    def __init__(self, **kwargs):
        self.topwidget = widgets.VBox()
        super(DeviceView, self).__init__(**kwargs)
        self.MainController = kwargs.get('MainController')
        self.DeviceSystem = self.MainController.DeviceSystem
        self.device_editor = None
        self.selected_devices = set()
        
#        col_names = ['id', 'name']
#        obj_names = ['NormalDevice', 'PixelMappedDevice']
#        self.device_list = DeviceTree(col_names=col_names, obj_names=obj_names, child_name_attr='none', 
#                                      show_dicts=False, base_dict=self.DeviceSystem.PatchedDevices, used_columns=[1])
#        self.device_list.widget.connect('selection_changed', self.on_device_list_selection_changed)
#        
#        self.topcontainer.pack_start(self.device_list.widget.topwidget, expand=True)
        
        table = widgets.Table(columns=8)
        self.device_controls = {}
        for key, val in self.DeviceSystem.DevicesByNum.iteritems():
            control = DeviceControl(device=val)
            control.connect('selection_changed', self.on_device_control_selection_changed)
            table.pack_start(control.topwidget, expand=True)
            self.device_controls.update({key:control})
        self.topcontainer.pack_start(table, expand=True)
        
        self.selected_controls = SelectedDeviceControl(MainController=self.MainController)
        self.topcontainer.pack_start(self.selected_controls.topwidget, expand=True)
        
        self.DeviceSystem.connect('new_device', self.on_ds_new_device)
        
        self.topwidget.show_all()
        
    def unlink(self):
        for control in self.device_controls.itervalues():
            control.unlink()
        self.DeviceSystem.disconnect(callback=self.on_ds_new_device)
        
    def set_current_device(self, obj):
        if self.device_editor is not None:
            self.device_editor.unlink()
            self.topcontainer.remove(self.device_editor.topwidget)
        self.device_editor = editors.DeviceEditor(MainController=self.MainController, device=obj)
        self.topcontainer.pack_start(self.device_editor.topwidget)
        
    def on_device_list_selection_changed(self, **kwargs):
        obj = kwargs.get('obj')
        state = kwargs.get('state')
        if state and hasattr(obj, 'id'):
            self.set_current_device(obj)
            
    def on_device_control_selection_changed(self, **kwargs):
        device = kwargs.get('device')
        if kwargs.get('state'):
            self.selected_devices.add(device)
            self.selected_controls.add_device(device)
        else:
            self.selected_devices.discard(device)
            self.selected_controls.del_device(device)
        #self.selected_controls.update_selected(self.selected_devices)
        
    def on_ds_new_device(self, **kwargs):
        #self.device_list.tree.refresh_all()
        pass
        
class DeviceControl(BaseObject):
    def __init__(self, **kwargs):
        super(DeviceControl, self).__init__(**kwargs)
        self.register_signal('selection_changed')
        self.device = kwargs.get('device')
        self._selected = False
        self.topwidget = widgets.Frame(label=self.device.device_num)
        self.lbl_name = widgets.Label(self.device.name)
        self.topwidget.pack_start(self.lbl_name)
        self.widgets = {}
        dimmer = self.device.Groups.get('Dimmer')
        if dimmer:
            widget = widgets.VSlider(attribute=dimmer)
            self.topwidget.pack_start(widget.topwidget, expand=True)
            self.widgets.update({'Dimmer':widget})
        color = self.device.Groups.get('Color')
        if color:
            widget = widgets.ColorBtn()
            self.topwidget.pack_start(widget.topwidget)
            color.connect('value_changed', self.on_color_group_value_changed)
            self.widgets.update({'Color':widget})
            
#        dimmer = None
#        colors = {}
#        for key, val in self.device.Attributes.iteritems():
#            if val.name == 'Dimmer':
#                dimmer = val
#            elif val.name.lower() in ['red', 'green', 'blue']:
#                colors.update({val.name.lower():val})
#        if dimmer:
#            widget = widgets.VSlider(attribute=dimmer)
#            self.topwidget.pack_start(widget.topwidget, expand=True)
#            self.widgets.update({key:widget})
##        elif 'Dimmer' in self.device.Groups:
##            widget = widgets.VSlider(attribute=self.device.Groups['Dimmer'])
##            self.topwidget.pack_start(widget.topwidget, expand=True)
##            self.widgets.update({'Dimmer':widget})
#        if len(colors) == 3:
#            widget = widgets.ColorBtn()
#            self.topwidget.pack_start(widget.topwidget)
#            self.widgets.update({'Color':widget})
#            for attrib in colors.itervalues():
#                attrib.connect('value_changed', self.on_color_attrib_value_changed)
#            self.color_attribs = colors
            
#        if 'Color' in self.device.Groups:
#            widget = widgets.ColorBtn()
#            self.device.Groups['Color'].connect('value_changed', self.on_color_group_value_changed)
#            self.topwidget.pack_start(widget.topwidget)
#            self.widgets.update({'Color':widget})
            
        self.btn_select = widgets.ToggleBtn(label='Select', src_object=self, src_attr='selected')
        self.topwidget.pack_start(self.btn_select.widget)
        self.topwidget.show_all()
        
    def unlink(self):
        for widget in self.widgets.itervalues():
            widget.unlink()
        #if 'Color' in self.device.Groups:
            #self.device.Groups['Color'].disconnect(callback=self.on_color_group_value_changed)
        if hasattr(self, 'color_attribs'):
            for attrib in self.color_attribs.itervalues():
                attrib.disconnect(callback=self.on_color_attrib_value_changed)
    def on_color_attrib_value_changed(self, **kwargs):
        d = {}
        for key, val in self.color_attribs.iteritems():
            d.update({key:val.value})
        self.widgets['Color'].update_widget_color(**d)
        
    def on_color_group_value_changed(self, **kwargs):
        value = kwargs.get('value')
        d = {}
        for x, key in enumerate(['red', 'green', 'blue']):
            d.update({key:value[x]})
        self.widgets['Color'].update_widget_color(**d)
        
    @property
    def selected(self):
        return self._selected
    @selected.setter
    def selected(self, value):
        if value != self._selected:
            self._selected = value
            self.btn_select.on_object_value_changed()
            self.emit('selection_changed', state=value, device=self.device)
        
class SelectedDeviceControl(BaseObject):
    def __init__(self, **kwargs):
        super(SelectedDeviceControl, self).__init__(**kwargs)
        self.MainController = kwargs.get('MainController')
        self.DeviceSystem = self.MainController.DeviceSystem
        self.selected_devices = set()
        self.topwidget = widgets.VBox()
        self.control_container = widgets.Table(columns=4)
        self.device_group = self.MainController.Selection
        self.controls = {}
        self.groups = set()
        self.proxy_groups = {}
        self.dummy_attribs = {}
        table = widgets.Table(columns=2, rows=2)
        self.testpalette = Palette(name='test')
        table.pack_start(self.testpalette.topwidget)
        btn = widgets.Button(label='test fade')
        btn.connect('clicked', self.on_btn_test_clicked)
        table.pack_start(btn)
        self.test_clicked = False
        self.topwidget.pack_start(table)
        self.build_controls()
        self.topwidget.pack_start(self.control_container)
        self.topwidget.show_all()
    def on_btn_test_clicked(self, btn):
        pass
        
    def build_controls(self):
        d = {'Dimmer':{'wid_cls':widgets.VSlider, 'wid_kwargs':{'attribute':'__obj__'}}, 
             'Position':{'wid_cls':clutter_bases.XYWidget, 'wid_kwargs':{'value_range':[[0, 255], [0, 255]]}, 
                         'signal':'position_changed', 'callback':self.on_xy_position_changed}, 
             'Color':{'wid_cls':widgets.ColorSelection, 'signal':'color_changed', 
                      'callback':self.on_color_widget_changed}}
        for key in ['Dimmer', 'Position', 'Color']:
            val = d[key]
            group = self.device_group.AttributeGroups[key]
            c_kwargs = val.get('wid_kwargs', {})
            for kwkey in c_kwargs.iterkeys():
                if c_kwargs[kwkey] == '__obj__':
                    c_kwargs[kwkey] = group
            control = val['wid_cls'](**c_kwargs)
            if 'signal' in val:
                control.connect(val['signal'], val['callback'])
            self.control_container.pack_start(control.topwidget)
            self.controls.update({key:control})
            
    def add_device(self, device):
        self.selected_devices.add(device)
        self.device_group.add_devices(device)
    def del_device(self, device):
        self.selected_devices.discard(device)
        self.device_group.del_member(device.id)
    def clear_all(self):
        for control in self.controls.itervalues():
            control.unlink()
            self.control_container.remove(control.topwidget)
        self.groups.clear()
        self.proxy_groups.clear()
        self.controls.clear()
    def on_color_widget_changed(self, **kwargs):
        color = kwargs.get('color')
        color_list = [color[key] for key in ['red', 'green', 'blue']]
        self.device_group.AttributeGroups['Color'].value = color_list
        #for device in self.selected_devices:
        #    if 'Color' in device.Groups:
        #        device.Groups['Color'].value = color_list
    def on_xy_position_changed(self, **kwargs):
        pos = kwargs.get('position')
        self.device_group.AttributeGroups['Position'].value = pos
        #for device in self.selected_devices:
        #    if 'Position' in device.Groups:
        #        device.Groups['Position'].value = pos

class Palette(BaseObject):
    button_types = {'button':widgets.Button, 'color':widgets.ColorBtn}
    def __init__(self, **kwargs):
        super(Palette, self).__init__(**kwargs)
        self.name = kwargs.get('name', '')
        self.grid_size = kwargs.get('grid_size', (8, 2))
        self.button_type = kwargs.get('button_type', 'button')
        self.buttons = []
        table = widgets.Table(columns=self.grid_size[0], rows=self.grid_size[1], homogeneous=True)
        self.topwidget = widgets.Expander(label=self.name, topwidget=table)
        self.build_buttons()
        self.topwidget.show_all()
    def build_buttons(self):
        cls = self.button_types.get(self.button_type)
        i = 0
        for y in range(self.grid_size[1]):
            for x in range(self.grid_size[0]):
                i += 1
                btn = cls(label=str(i))
                btn.connect('clicked', self.on_button_clicked, i)
                self.topwidget.attach(btn, x, x+1, y, y+1)
                self.buttons.append(btn)
    def on_button_clicked(self, btn, index):
        print 'clicky:', index
